package com.itheima.sevrice.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.bean.Category;
import com.itheima.bean.Dish;
import com.itheima.bean.DishFlavor;
import com.itheima.common.PageParam;
import com.itheima.dao.DishDao;
import com.itheima.dto.DishDto;
import com.itheima.sevrice.CategoryService;
import com.itheima.sevrice.DishFlavorService;
import com.itheima.sevrice.DishService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@Service
@Transactional
public class DishServiceImpl implements DishService {

    @Autowired(required = false)
    private DishDao dishDao;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private DishFlavorService dishFlavorService;

    @Autowired(required = false)
    private RedisTemplate redisTemplate;

    /**
     * 分页查询
     *
     * @param pageParam
     * @return
     */
    @Override
    public IPage<DishDto> findPage(PageParam pageParam) {
        //构建分页条件对象
        IPage<Dish> iPage = new Page<>(pageParam.getPage(), pageParam.getPageSize());
        //构建条件对象
        LambdaQueryWrapper<Dish> lqw = new LambdaQueryWrapper<>();
        //追加条件
        lqw.like(pageParam.getName() != null, Dish::getName, pageParam.getName());
        //执行条件
        IPage<Dish> page = dishDao.selectPage(iPage, lqw);

        //创建DishDto 对象 包装total 总记录数和 当前页集合数
        IPage<DishDto> dtoIPage = new Page<>();
        dtoIPage.setTotal(page.getTotal());

        List<DishDto> dishDtoList = page.getRecords().stream().map(dish -> {
            //遍历每一道菜 根据菜的id 去查是一个菜品套餐对象
            Category category = categoryService.findByDishId(dish.getCategoryId());

            DishDto dishDto = new DishDto();
            dishDto.setCategoryName(category.getName());

            BeanUtils.copyProperties(dish, dishDto);

            //2.3 设置dishDao 里面的口味 数据
            //2.3.1先根据菜品的id 去查询菜品口味表，得到菜品的口味数据
            List<DishFlavor> dishFlavorList = dishFlavorService.findByDishId(dish.getId());
            dishDto.setFlavors(dishFlavorList);

            return dishDto;
        }).collect(Collectors.toList());
        dtoIPage.setRecords(dishDtoList);

        return dtoIPage;
    }

    /**
     * 添加菜品，需要添加口味数据
     *
     * @param dishDto
     * @return
     */
    @Override
    public int addDish(DishDto dishDto) {
        //执行条件
        int row1 = dishDao.insert(dishDto);
        //判断是否添加成功
        if (row1 > 0) {
            //追加添加口味数据
            List<DishFlavor> flavors = dishDto.getFlavors();

            int row2 = 0;
            if (flavors != null && flavors.size() > 0) {

                for (DishFlavor flavor : flavors) {
                    //设置口味是那一道菜的id
                    flavor.setDishId(dishDto.getId());
                    //调用口味表 添加口味数据
                    row2 += dishFlavorService.addDishFlavor(flavor);
                }
                return row2 == flavors.size() ? 1 : 0;
            }
        }
        //当保存某个菜品分类下的菜品时，需要删除此菜品分类的数据
        String key="DISH_"+dishDto.getCategoryId()+dishDto.getStatus();
        redisTemplate.delete(key);
        return row1;
    }

    /**
     * 删除菜品 1.前置条件是需要菜品的售卖状态 必须是停售的状态
     * 2.这里删除菜品时还需要把菜品的口味数据也要删除
     *
     * @param ids 删除的菜品id 集合
     * @return
     */
    @Override
    public int deleteDish(List<Long> ids) {
        //构建条件查询对象
        LambdaQueryWrapper<Dish> lqw = new LambdaQueryWrapper<>();
        //追加条件
        lqw.eq(Dish::getStatus, 0);
        lqw.in(Dish::getId, ids);
        //执行条件
        int row = dishDao.delete(lqw);
        if (row > 0) {
            //删除菜品绑定的口味数据
            dishFlavorService.deleteDishFlavor(ids);
        }
        return row;
    }

    /**
     * 修改菜品的售卖状态
     *
     * @param ids
     * @return
     */
    @Override
    public int updateStatus(Integer status, List<Long> ids) {
        //构建条件查询对象
        UpdateWrapper<Dish> wrapper = new UpdateWrapper<>();
        wrapper.set("status", status).in("id", ids);
        return dishDao.update(null, wrapper);

       /* LambdaQueryWrapper<Dish> lqw = new LambdaQueryWrapper<>();
        lqw.in(Dish::getId,ids);
        lqw.eq(Dish::getStatus,status);
        return dishDao.update(null,lqw);*/
    }

    /**
     * 更新菜品
     *
     * @param dishDto
     * @return
     */
    @Override
    public int updateDish(DishDto dishDto) {

        //根据菜品的ID 更新菜品数据
        int row1 = dishDao.updateById(dishDto);

        //需要更新口味表的数据
        //2.1 可以这样做，先把原来的口味数据删除了，在添加页面传递过来的口味数据
        //2.2 根据菜品id去删除口味表的数据
         dishFlavorService.deleteDishIdFlavor(dishDto.getId());
        //重新获取页面传过来的dishflavor 数据
        List<DishFlavor> flavors = dishDto.getFlavors();
        int row3 = 0;
        if (flavors != null && flavors.size() > 0) {
            //循环遍历口味数据，并追加到菜品
            for (DishFlavor dishFlavor : flavors) {
                //设置口味 追加到菜品上
                dishFlavor.setDishId(dishDto.getId());
                //添加口味
                row3 += dishFlavorService.addDishFlavor(dishFlavor);
            }
            return row3 == flavors.size() ? 1 : 0;
        }
        return row1;
    }

    /**
     * 根据菜品分类查询菜品
     *
     * @param categoryId
     * @return
     */
    @Override
    public List<DishDto> findByCategoryId(Long categoryId, Integer status) {
        //缓存菜品数据 第二步a，查询redis 看缓存中是否有此菜品
        //注意：将集合的数据转为String 存入redis的
        String key="DISH_"+categoryId+status;
        String dishListStr = (String) redisTemplate.opsForValue().get(key);
        //缓存菜品数据 第三步 ，假设缓存中有数据，直接返回
        if (StringUtils.isNotEmpty(dishListStr)){
            log.debug("****************查询redis数据****************");
            //将string 转为list
            return JSON.parseObject(dishListStr,List.class);
        }
        //c，假设缓存数据中没有数据，则查询数据库表


        LambdaQueryWrapper<Dish> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Dish::getCategoryId,categoryId);
        lqw.eq(status!=null, Dish::getStatus,status);
        List<Dish> dishes = dishDao.selectList(lqw);

        //将这里得到的dishes 集合 循环遍历 映射 包装 菜品的口味数据  得到dishDto
        List<DishDto> dtoList = dishes.stream().map(dish -> {
            //构建dishDto
            DishDto dishDto = new DishDto();
            //拷贝dish 数据 到 dishDto 上
            BeanUtils.copyProperties(dish, dishDto);
            //更加dishId 查询口味数据
            List<DishFlavor> flavorList = dishFlavorService.findByDishId(dish.getId());
            //设置dishDto 口味数据
            dishDto.setFlavors(flavorList);
            return dishDto;
        }).collect(Collectors.toList());

        //d 将数据库表中的最新数据 存入缓存中
        //注意要将集合转为String
        redisTemplate.opsForValue().set(key,JSON.toJSONString(dtoList));

        //返回 dishDto
        return dtoList;
    }

    /**
     * 根据菜品id 查询该菜品
     *
     * @param id
     * @return
     */
    @Override
    public List<Dish> findById(List<Long> id) {
        LambdaQueryWrapper<Dish> lqw = new LambdaQueryWrapper<>();
        lqw.in(Dish::getId,id);
        return dishDao.selectList(lqw);
    }

    /**
     * 根据菜品id 查询该菜品
     *
     * @param id
     * @return
     */
    @Override
    public Dish findById(Long id) {
        return dishDao.selectById(id);
    }


}
